nv.defineSingleton("nv.util.Url", function ($this) {
    $this.getQueryString = function (params) {
        if (typeof params == 'string') {
            return params;
        }
        var queryString = '';
        nv.array.iterate(params, function (key, value) {
            if (typeof (value) == 'object') {
                nv.array.iterate(value, function (innerKey, innerValue) {
                    if (queryString !== '') {
                        queryString += '&';
                    }
                    queryString += encodeURIComponent(key) + '[' + encodeURIComponent(innerKey) + ']=' + encodeURIComponent(innerValue);
                });
            } else if (typeof (value) == 'undefined') {} else {
                if (queryString !== '') {
                    queryString += '&';
                }
                queryString += encodeURIComponent(key) + '=' + encodeURIComponent(value);
            }
        });
        return queryString;
    };
    $this.parseQuery = function (query) {
        if (!query) {
            return {};
        }
        if (query.length > 0 && query.charAt(0) == '?') query = query.substr(1);
        var params = (query + '').split('&');
        var obj = {};
        var params_length = 0,
            tmp = '',
            x = 0;
        params_length = params.length;
        for (x = 0; x < params_length; x++) {
            tmp = params[x].split('=');
            obj[unescape(tmp[0])] = unescape(tmp[1]).replace(/[+]/g, ' ');
        }
        return obj;
    };
    $this.addToQueryString = function (url, params) {
        params = $this.getQueryString(params);
        if (url.indexOf("?") == -1) {
            url += "?" + params;
        } else {
            url += "&" + params;
        }
        return url;
    };
    $this.makeUrl = function (url_parts) {
        var url = "";
        if (typeof url_parts.scheme != "undefined") {
            url += url_parts.scheme + "://";
        }
        if (typeof url_parts.user != "undefined") {
            url += url_parts.user;
        }
        if (typeof url_parts.pass != "undefined") {
            url += ":" + url_parts.pass;
        }
        if (typeof url_parts.user != "undefined" || typeof url_parts.pass != "undefined") {
            url += "@";
        }
        if (typeof url_parts.host != "undefined") {
            url += url_parts.host;
        }
        if (typeof url_parts.port != "undefined") {
            url += ":" + url_parts.port;
        }
        if (typeof url_parts.path != "undefined") {
            url += url_parts.path;
        }
        if (typeof url_parts.query != "undefined" && url_parts.query) {
            if (url_parts.query.substring(0, 1) != "?") {
                url += "?";
            }
            url += url_parts.query;
        }
        if (typeof url_parts.fragment != "undefined") {
            if (url_parts.fragment[0] != "#") {
                url += "#";
            }
            url += url_parts.fragment;
        }
        return url;
    };
    $this.parseUrl = function (str) {
        if (str.length > 2 && str[0] == '/' && str[1] == '/') {
            str = window.location.protocol + str;
        }
        var o = {
            strictMode: false,
            key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"],
            q: {
                name: "queryKey",
                parser: /(?:^|&)([^&=]*)=?([^&]*)/g
            },
            parser: {
                strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
                loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
            }
        };
        var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
            uri = {}, i = 14;
        while (i--) uri[o.key[i]] = m[i] || "";
        var retArr = {};
        if (uri.protocol !== '') retArr.scheme = uri.protocol;
        if (uri.host !== '') retArr.host = uri.host;
        if (uri.port !== '') retArr.port = uri.port;
        if (uri.user !== '') retArr.user = uri.user;
        if (uri.password !== '') retArr.pass = uri.password;
        if (uri.path !== '') retArr.path = uri.path;
        if (uri.query !== '') retArr.query = uri.query;
        if (uri.anchor !== '') retArr.fragment = uri.anchor;
        return retArr;
    };
});
if (nv.CreateNamespace("nv.util.URL")) {
    nv.deprecated("nv.util.URL.GetQueryString", nv.util.Url.getQueryString);
    nv.deprecated("nv.util.URL.MakeUrl", nv.util.Url.makeUrl);
    nv.deprecated("nv.util.URL.ParseQuery", nv.util.Url.parseQuery);
    nv.deprecated("nv.util.URL.ParseUrl", nv.util.Url.parseUrl);
}